home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 March / CMCD0305.ISO / Software / Freeware / Programare / nvu / nvu-0.80-win32-installer-full.exe / {app} / chrome / help.jar / content / help / help.js < prev    next >
Text File  |  2005-01-28  |  26KB  |  800 lines

  1.  
  2. var helpBrowser;
  3. var helpWindow;
  4. var helpSearchPanel;
  5. var emptySearch;
  6. var emptySearchText
  7. var emptySearchLink
  8. var helpTocPanel;
  9. var helpIndexPanel;
  10. var helpGlossaryPanel;
  11.  
  12. const NC = "http://home.netscape.com/NC-rdf#";
  13. const SN = "rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  14. const XML = "http://www.w3.org/XML/1998/namespace#"
  15. const MAX_LEVEL = 40; // maximum depth of recursion in search datasources.
  16. const MAX_HISTORY_MENU_ITEMS = 6;
  17.  
  18. const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  19.     .getService(Components.interfaces.nsIRDFService);
  20. const RDF_ROOT = RDF.GetResource("urn:root");
  21. const NC_PANELLIST = RDF.GetResource(NC + "panellist");
  22. const NC_PANELID = RDF.GetResource(NC + "panelid");
  23. const NC_EMPTY_SEARCH_TEXT = RDF.GetResource(NC + "emptysearchtext");
  24. const NC_EMPTY_SEARCH_LINK = RDF.GetResource(NC + "emptysearchlink");
  25. const NC_DATASOURCES = RDF.GetResource(NC + "datasources");
  26. const NC_SUBHEADINGS = RDF.GetResource(NC + "subheadings");
  27. const NC_NAME = RDF.GetResource(NC + "name");
  28. const NC_CHILD = RDF.GetResource(NC + "child");
  29. const NC_LINK = RDF.GetResource(NC + "link");
  30. const NC_TITLE = RDF.GetResource(NC + "title");
  31. const NC_BASE = RDF.GetResource(NC + "base");
  32. const NC_DEFAULTTOPIC = RDF.GetResource(NC + "defaulttopic");
  33.  
  34. const RDFCUtils = Components.classes["@mozilla.org/rdf/container-utils;1"]
  35.     .getService().QueryInterface(Components.interfaces.nsIRDFContainerUtils);
  36. const RDFContainer = Components.classes["@mozilla.org/rdf/container;1"]
  37.     .getService(Components.interfaces.nsIRDFContainer);
  38. const CONSOLE_SERVICE = Components.classes['@mozilla.org/consoleservice;1']
  39.     .getService(Components.interfaces.nsIConsoleService);
  40.  
  41. var urnID = 0;
  42. var RE;
  43.  
  44. var helpFileURI;
  45. var helpFileDS;
  46. var helpBaseURI;
  47.  
  48. const defaultHelpFile = "chrome://help/locale/help.rdf";
  49. const defaultTopic = "use-help";
  50. var searchDatasources = "rdf:null";
  51. var searchDS = null;
  52.  
  53. const NSRESULT_RDF_SYNTAX_ERROR = 0x804e03f7;
  54.  
  55. function displayTopic(topic) {
  56.     // Get the page to open.
  57.     var uri = getLink(topic);
  58.  
  59.     // Use default topic if specified topic is not found.
  60.     if (!uri) {
  61.         uri = getLink(defaultTopic);
  62.     }
  63.  
  64.     // Load the page.
  65.     loadURI(uri);
  66. }
  67.  
  68. function init() {
  69.     // Cache panel references.
  70.     helpWindow = document.getElementById("help");
  71.     helpSearchPanel = document.getElementById("help-search-panel");
  72.     helpTocPanel = document.getElementById("help-toc-panel");
  73.     helpIndexPanel = document.getElementById("help-index-panel");
  74.     helpGlossaryPanel = document.getElementById("help-glossary-panel");
  75.     helpBrowser = document.getElementById("help-content");
  76.  
  77.     // Get the content pack, base URL, and help topic
  78.     var helpTopic = defaultTopic;
  79.     if ("arguments" in window
  80.             && window.arguments[0]
  81.             instanceof Components.interfaces.nsIDialogParamBlock) {
  82.         helpFileURI = window.arguments[0].GetString(0);
  83.         // trailing "/" included.
  84.         helpBaseURI = helpFileURI.substring(0, helpFileURI.lastIndexOf("/")+1);
  85.         helpTopic = window.arguments[0].GetString(1);
  86.     }
  87.  
  88.     loadHelpRDF();
  89.     displayTopic(helpTopic);
  90.  
  91.     // Move to Center of Screen
  92.     const width = document.documentElement.getAttribute("width");
  93.     const height = document.documentElement.getAttribute("height");
  94.     window.moveTo((screen.availWidth - width) / 2, (screen.availHeight - height) / 2);
  95.  
  96.     // Initialize history.
  97.     getWebNavigation().sessionHistory = Components.classes["@mozilla.org/browser/shistory;1"]
  98.         .createInstance(Components.interfaces.nsISHistory);
  99.     window.XULBrowserWindow = new nsHelpStatusHandler();
  100.  
  101.     //Start the status handler.
  102.     window.XULBrowserWindow.init();
  103.  
  104.     // Hook up UI through Progress Listener
  105.     const interfaceRequestor = helpBrowser.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  106.     const webProgress = interfaceRequestor.getInterface(Components.interfaces.nsIWebProgress);
  107.  
  108.     webProgress.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  109.  
  110.     //Display the Table of Contents
  111.     showPanel("help-toc");
  112.  
  113.     // initialize the customizeDone method on the customizeable toolbar
  114.     var toolbox = document.getElementById("help-toolbox");
  115.     toolbox.customizeDone = ToolboxCustomizeDone;
  116.  
  117.     var toolbarset = document.getElementById("customToolbars");
  118.     toolbox.toolbarset = toolbarset;
  119.  
  120.     // Set the text of the sidebar toolbar button to "Hide Sidebar" taken the properties file.
  121.     // This is needed so that it says "Toggle Sidebar" in toolbar customization, but outside
  122.     // of it, it says either "Show Sidebar" or "Hide Sidebar".
  123.     document.getElementById("help-sidebar-button").label =
  124.            document.getElementById("bundle_help").getString("hideSidebarLabel");
  125. }
  126.  
  127. function loadHelpRDF() {
  128.     if (!helpFileDS) {
  129.         try {
  130.             helpFileDS = RDF.GetDataSourceBlocking(helpFileURI);
  131.         } catch (e if (e.result == NSRESULT_RDF_SYNTAX_ERROR)) {
  132.             log("Help file: " + helpFileURI + " contains a syntax error.");
  133.         } catch (e) {
  134.             log("Help file: " + helpFileURI + " was not found.");
  135.         }
  136.         try {
  137.             helpWindow.setAttribute("title",
  138.                 getAttribute(helpFileDS, RDF_ROOT, NC_TITLE, ""));
  139.             helpBaseURI = getAttribute(helpFileDS, RDF_ROOT, NC_BASE, helpBaseURI);
  140.             defaultTopic = getAttribute(helpFileDS,
  141.                 RDF_ROOT, NC_DEFAULTTOPIC, "welcome");
  142.  
  143.             var panelDefs = helpFileDS.GetTarget(RDF_ROOT, NC_PANELLIST, true);
  144.             RDFContainer.Init(helpFileDS, panelDefs);
  145.             var iterator = RDFContainer.GetElements();
  146.             while (iterator.hasMoreElements()) {
  147.                 var panelDef = iterator.getNext();
  148.                 var panelID = getAttribute(helpFileDS, panelDef, NC_PANELID,
  149.                     null);
  150.  
  151.                 var datasources = getAttribute(helpFileDS, panelDef,
  152.                     NC_DATASOURCES, "rdf:none");
  153.                 datasources = normalizeLinks(helpBaseURI, datasources);
  154.                 // Cache Additional Datasources to Augment Search Datasources.
  155.                 if (panelID == "search") {
  156.                     emptySearchText = getAttribute(helpFileDS, panelDef,
  157.                         NC_EMPTY_SEARCH_TEXT, null) || "No search items found.";
  158.                     emptySearchLink = getAttribute(helpFileDS, panelDef,
  159.                         NC_EMPTY_SEARCH_LINK, null) || "about:blank";
  160.                     searchDatasources = datasources;
  161.                     // Don't try to display them yet!
  162.                     datasources = "rdf:null";
  163.                 }
  164.  
  165.                 // Cache TOC Datasources for Use by ID Lookup.
  166.                 var tree = document.getElementById("help-" + panelID + "-panel");
  167.                 loadDatabasesBlocking(datasources);
  168.                 tree.setAttribute("datasources", datasources);
  169.             }
  170.         } catch (e) {
  171.             log(e + "");
  172.         }
  173.     }
  174. }
  175.  
  176. function loadDatabasesBlocking(datasources) {
  177.     var ds = datasources.split(/\s+/);
  178.     for (var i=0; i < ds.length; ++i) {
  179.         if (ds[i] == "rdf:null" || ds[i] == "")
  180.             continue;
  181.         try {
  182.             // We need blocking here to ensure the database is loaded so
  183.             // getLink(topic) works.
  184.             var datasource = RDF.GetDataSourceBlocking(ds[i]);
  185.         } catch (e) {
  186.             log("Datasource: " + ds[i] + " was not found.");
  187.         }
  188.     }
  189. }
  190.  
  191. function normalizeLinks(helpBaseURI, links) {
  192.     if (!helpBaseURI) {
  193.         return links;
  194.     }
  195.     var ls = links.split(/\s+/);
  196.     if (ls.length == 0) {
  197.         return links;
  198.     }
  199.     for (var i=0; i < ls.length; ++i) {
  200.         if (ls[i] == "") {
  201.             continue;
  202.         }
  203.         if (ls[i].substr(0,7) != "chrome:" && ls[i].substr(0,4) != "rdf:") {
  204.             ls[i] = helpBaseURI + ls[i];
  205.         }
  206.     }
  207.     return ls.join(" ");
  208. }
  209.  
  210. function getLink(ID) {
  211.     if (!ID) {
  212.         return null;
  213.     }
  214.     // Note resources are stored in fileURL#ID format.
  215.     // We have one possible source for an ID for each datasource in the
  216.     // composite datasource.
  217.     // The first ID which matches is returned.
  218.     var tocTree = document.getElementById("help-toc-panel");
  219.     var tocDS = tocTree.database;
  220.     if (tocDS == null) {
  221.         return null;
  222.     }
  223.     var tocDatasources = tocTree.getAttribute("datasources");
  224.     var ds = tocDatasources.split(/\s+/);
  225.     for (var i=0; i < ds.length; ++i) {
  226.         if (ds[i] == "rdf:null" || ds[i] == "") {
  227.             continue;
  228.         }
  229.         try {
  230.             var rdfID = ds[i] + "#" + ID;
  231.             var resource = RDF.GetResource(rdfID);
  232.             if (resource) {
  233.                 var link = tocDS.GetTarget(resource, NC_LINK, true);
  234.                 if (link) {
  235.                     link = link.QueryInterface(Components.interfaces
  236.                         .nsIRDFLiteral);
  237.                     if (link) {
  238.                         return link.Value;
  239.                     } else {
  240.                         return null;
  241.                     }
  242.                 }
  243.             }
  244.         } catch (e) {
  245.             log(rdfID + " " + e);
  246.         }
  247.     }
  248.     return null;
  249. }
  250.  
  251. function getHelpFileURI() {
  252.     return helpFileURI;
  253. }
  254.  
  255. function getBrowser() {
  256.   return helpBrowser;
  257. }
  258.  
  259. function getWebNavigation() {
  260.   try {
  261.     return helpBrowser.webNavigation;
  262.   } catch (e)
  263.   {
  264.     return null;
  265.   }
  266. }
  267.  
  268. function loadURI(uri) {
  269.     if (uri.substr(0,7) != "chrome:") {
  270.         uri = helpBaseURI + uri;
  271.     }
  272.     getWebNavigation().loadURI(uri, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE,
  273.         null, null, null);
  274. }
  275.  
  276. function goBack() {
  277.   try
  278.   {
  279.     getWebNavigation().goBack();
  280.   } catch (e)
  281.   {
  282.   }
  283. }
  284.  
  285. /* copied from browser.js */
  286. function BrowserReloadWithFlags(reloadFlags) {
  287.     /* First, we'll try to use the session history object to reload so 
  288.      * that framesets are handled properly. If we're in a special 
  289.      * window (such as view-source) that has no session history, fall 
  290.      * back on using the web navigation's reload method.
  291.      */
  292.  
  293.     var webNav = getWebNavigation();
  294.     try {
  295.       var sh = webNav.sessionHistory;
  296.       if (sh)
  297.         webNav = sh.QueryInterface(Components.interfaces.nsIWebNavigation);
  298.     } catch (e) {
  299.     }
  300.  
  301.     try {
  302.       webNav.reload(reloadFlags);
  303.     } catch (e) {
  304.     }
  305. }
  306.  
  307. function reload() {
  308.   const reloadFlags = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE;
  309.   return BrowserReloadWithFlags(reloadFlags);
  310. }
  311.  
  312. function goForward() {
  313.     try
  314.     {
  315.       getWebNavigation().goForward();
  316.     } catch(e)
  317.     {
  318.     }
  319. }
  320.  
  321. function goHome() {
  322.     // Load "Welcome" page
  323.     loadURI("chrome://help/locale/firefox_welcome.xhtml");
  324. }
  325.  
  326. function print() {
  327.     try {
  328.         _content.print();
  329.     } catch (e) {
  330.     }
  331. }
  332.  
  333. function FillHistoryMenu(aParent, aMenu)
  334.   {
  335.     // Remove old entries if any
  336.     deleteHistoryItems(aParent);
  337.  
  338.     var sessionHistory = getWebNavigation().sessionHistory;
  339.  
  340.     var count = sessionHistory.count;
  341.     var index = sessionHistory.index;
  342.     var end;
  343.     var j;
  344.     var entry;
  345.  
  346.     switch (aMenu)
  347.       {
  348.         case "back":
  349.           end = (index > MAX_HISTORY_MENU_ITEMS) ? index - MAX_HISTORY_MENU_ITEMS : 0;
  350.           if ((index - 1) < end) return false;
  351.           for (j = index - 1; j >= end; j--)
  352.             {
  353.               entry = sessionHistory.getEntryAtIndex(j, false);
  354.               if (entry)
  355.                 createMenuItem(aParent, j, entry.title);
  356.             }
  357.           break;
  358.         case "forward":
  359.           end  = ((count-index) > MAX_HISTORY_MENU_ITEMS) ? index + MAX_HISTORY_MENU_ITEMS : count;
  360.           if ((index + 1) >= end) return false;
  361.           for (j = index + 1; j < end; j++)
  362.             {
  363.               entry = sessionHistory.getEntryAtIndex(j, false);
  364.               if (entry)
  365.                 createMenuItem(aParent, j, entry.title);
  366.             }
  367.           break;
  368.       }
  369.     return true;
  370.   }
  371.  
  372. function createMenuItem( aParent, aIndex, aLabel)
  373.   {
  374.     var menuitem = document.createElement( "menuitem" );
  375.     menuitem.setAttribute( "label", aLabel );
  376.     menuitem.setAttribute( "index", aIndex );
  377.     aParent.appendChild( menuitem );
  378.   }
  379.  
  380. function deleteHistoryItems(aParent)
  381. {
  382.   var children = aParent.childNodes;
  383.   for (var i = children.length - 1; i >= 0; --i)
  384.     {
  385.       var index = children[i].getAttribute("index");
  386.       if (index)
  387.         aParent.removeChild(children[i]);
  388.     }
  389. }
  390.  
  391. function createBackMenu(event) {
  392.     return FillHistoryMenu(event.target, "back");
  393. }
  394.  
  395. function createForwardMenu(event) {
  396.     return FillHistoryMenu(event.target, "forward");
  397. }
  398.  
  399. function gotoHistoryIndex(aEvent) {
  400.     var index = aEvent.target.getAttribute("index");
  401.     if (!index) {
  402.         return false;
  403.     }
  404.     try {
  405.         getWebNavigation().gotoIndex(index);
  406.     } catch(ex) {
  407.         return false;
  408.     }
  409.     return true;
  410. }
  411.  
  412. function nsHelpStatusHandler() {
  413.   this.init();
  414. }
  415.  
  416. nsHelpStatusHandler.prototype = {
  417.  
  418.     onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
  419.     {
  420.       const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  421.  
  422.       if (aStateFlags & nsIWebProgressListener.STATE_START) {
  423.         if (this.throbberElement)
  424.           this.throbberElement.setAttribute("busy", "true");
  425.       } else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
  426.         if (aRequest && this.throbberElement) {
  427.           this.throbberElement.removeAttribute("busy");
  428.         }
  429.       }
  430.     },
  431.     onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
  432.         aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
  433.     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
  434.     onSecurityChange : function(aWebProgress, aRequest, state) {},
  435.     onLocationChange : function(aWebProgress, aRequest, aLocation) {
  436.         UpdateBackForwardButtons();
  437.     },
  438.     QueryInterface : function(aIID) {
  439.         if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  440.                 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  441.                 aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
  442.                 aIID.equals(Components.interfaces.nsISupports)) {
  443.             return this;
  444.         }
  445.         throw Components.results.NS_NOINTERFACE;
  446.     },
  447.  
  448.     init : function()
  449.     {
  450.       this.throbberElement = document.getElementById("help-throbber");
  451.     },
  452.  
  453.     destroy : function()
  454.     {
  455.       //this needed to avoid memory leaks, see bug 60729
  456.       this.throbberElement = null;
  457.     },
  458.  
  459.     setJSStatus : function(status) {},
  460.     setJSDefaultStatus : function(status) {},
  461.     setOverLink : function(link) {}
  462. }
  463.  
  464. function UpdateBackForwardButtons() {
  465.     var backBroadcaster = document.getElementById("canGoBack");
  466.     var forwardBroadcaster = document.getElementById("canGoForward");
  467.     var webNavigation = getWebNavigation();
  468.  
  469.     // Avoid setting attributes on broadcasters if the value hasn't changed!
  470.     // Remember, guys, setting attributes on elements is expensive!  They
  471.     // get inherited into anonymous content, broadcast to other widgets, etc.!
  472.     // Don't do it if the value hasn't changed! - dwh
  473.  
  474.     var backDisabled = (backBroadcaster.getAttribute("disabled") == "true");
  475.     var forwardDisabled = (forwardBroadcaster.getAttribute("disabled") == "true");
  476.  
  477.     if (backDisabled == webNavigation.canGoBack) {
  478.       if (backDisabled)
  479.         backBroadcaster.removeAttribute("disabled");
  480.       else
  481.         backBroadcaster.setAttribute("disabled", true);
  482.     }
  483.  
  484.     if (forwardDisabled == webNavigation.canGoForward) {
  485.       if (forwardDisabled)
  486.         forwardBroadcaster.removeAttribute("disabled");
  487.       else
  488.         forwardBroadcaster.setAttribute("disabled", true);
  489.     }
  490. }
  491.  
  492. function getMarkupDocumentViewer() {
  493.     return helpBrowser.markupDocumentViewer;
  494. }
  495.  
  496. function showPanel(panelId) {
  497.     //hide other sidebar panels and show the panel name taken in.
  498.     helpSearchPanel.setAttribute("hidden", "true");
  499.     helpTocPanel.setAttribute("hidden", "true");
  500.     helpIndexPanel.setAttribute("hidden", "true");
  501.     helpGlossaryPanel.setAttribute("hidden", "true");
  502.     var thePanel = document.getElementById(panelId + "-panel");
  503.     thePanel.setAttribute("hidden","false");
  504.  
  505.     //remove the selected style from the previous panel selected.
  506.     var theButton = document.getElementById(panelId + "-btn");
  507.     document.getElementById("help-glossary-btn").removeAttribute("selected");
  508.     document.getElementById("help-index-btn").removeAttribute("selected");
  509.     document.getElementById("help-search-btn").removeAttribute("selected");
  510.     document.getElementById("help-toc-btn").removeAttribute("selected");
  511.     //add the selected style to the correct panel.
  512.     theButton.setAttribute("selected", "true");
  513.  
  514.     //focus the searchbox if the search sidebar panel is shown.
  515.     if (panelId == "help-search")
  516.       document.getElementById("findText").focus();
  517. }
  518.  
  519. function findParentNode(node, parentNode)
  520. {
  521.   if (node && node.nodeType == Node.TEXT_NODE) {
  522.     node = node.parentNode;
  523.   }
  524.   while (node) {
  525.     var nodeName = node.localName;
  526.     if (!nodeName)
  527.       return null;
  528.     nodeName = nodeName.toLowerCase();
  529.     if (nodeName == "body" || nodeName == "html" ||
  530.         nodeName == "#document") {
  531.       return null;
  532.     }
  533.     if (nodeName == parentNode)
  534.       return node;
  535.     node = node.parentNode;
  536.   }
  537.   return null;
  538. }
  539.  
  540. function onselect_loadURI(tree) {
  541.     try {
  542.         var resource = tree.view.getResourceAtIndex(tree.currentIndex);
  543.     var link = tree.database.GetTarget(resource, NC_LINK, true);
  544.     if (link) {
  545.             link = link.QueryInterface(Components.interfaces.nsIRDFLiteral);
  546.             loadURI(link.Value);
  547.         }
  548.     } catch (e) {
  549.     }// when switching between tabs a spurious row number is returned.
  550. }
  551.  
  552. function doFind() {
  553.     var searchTree = document.getElementById("help-search-tree");
  554.     var findText = document.getElementById("findText");
  555.  
  556.     // clear any previous results.
  557.     clearDatabases(searchTree.database);
  558.  
  559.     // split search string into separate terms and compile into regexp's
  560.     RE = findText.value.split(/\s+/);
  561.     for (var i=0; i < RE.length; ++i) {
  562.         if (RE[i] == "")
  563.             continue;
  564.  
  565.         RE[i] = new RegExp(RE[i], "i");
  566.     }
  567.     emptySearch = true;
  568.     // search TOC
  569.     var resultsDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
  570.         .createInstance(Components.interfaces.nsIRDFDataSource);
  571.     var tree = helpTocPanel;
  572.     var sourceDS = tree.database;
  573.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  574.  
  575.     // search glossary.
  576.     tree = helpGlossaryPanel;
  577.     sourceDS = tree.database;
  578.     // If the glossary has never been displayed this will be null (sigh!).
  579.     if (!sourceDS)
  580.         sourceDS = loadCompositeDS(tree.datasources);
  581.  
  582.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  583.  
  584.     // search index
  585.     tree = helpIndexPanel;
  586.     sourceDS = tree.database;
  587.     //If the index has never been displayed this will be null
  588.     if (!sourceDS)
  589.       sourceDS = loadCompositeDS(tree.datasources);
  590.  
  591.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  592.  
  593.     if (emptySearch)
  594.         assertSearchEmpty(resultsDS);
  595.     // Add the datasource to the search tree
  596.     searchTree.database.AddDataSource(resultsDS);
  597.     searchTree.builder.rebuild();
  598. }
  599.  
  600. function doEnabling() {
  601.     var findButton = document.getElementById("findButton");
  602.     var findTextbox = document.getElementById("findText");
  603.     findButton.disabled = !findTextbox.value;
  604. }
  605.  
  606. function clearDatabases(compositeDataSource) {
  607.     var enumDS = compositeDataSource.GetDataSources()
  608.     while (enumDS.hasMoreElements()) {
  609.         var ds = enumDS.getNext();
  610.         compositeDataSource.RemoveDataSource(ds);
  611.     }
  612. }
  613.  
  614. function doFindOnDatasource(resultsDS, sourceDS, resource, level) {
  615.     if (level > MAX_LEVEL) {
  616.         try {
  617.             log("Recursive reference to resource: " + resource.Value + ".");
  618.         } catch (e) {
  619.             log("Recursive reference to unknown resource.");
  620.         }
  621.         return;
  622.     }
  623.     // find all SUBHEADING children of current resource.
  624.     var targets = sourceDS.GetTargets(resource, NC_SUBHEADINGS, true);
  625.     while (targets.hasMoreElements()) {
  626.         var target = targets.getNext();
  627.         target = target.QueryInterface(Components.interfaces.nsIRDFResource);
  628.         // The first child of a rdf:subheading should (must) be a rdf:seq.
  629.         // Should we test for a SEQ here?
  630.         doFindOnSeq(resultsDS, sourceDS, target, level+1);
  631.     }
  632. }
  633.  
  634. function doFindOnSeq(resultsDS, sourceDS, resource, level) {
  635.     // load up an RDFContainer so we can access the contents of the current
  636.     // rdf:seq.
  637.     RDFContainer.Init(sourceDS, resource);
  638.     var targets = RDFContainer.GetElements();
  639.     while (targets.hasMoreElements()) {
  640.         var target = targets.getNext();
  641.         target = target.QueryInterface(Components.interfaces.nsIRDFResource);
  642.         var name = sourceDS.GetTarget(target, NC_NAME, true);
  643.         name = name.QueryInterface(Components.interfaces.nsIRDFLiteral);
  644.  
  645.         if (isMatch(name.Value)) {
  646.             // we have found a search entry - add it to the results datasource.
  647.  
  648.             // Get URL of html for this entry.
  649.             var link = sourceDS.GetTarget(target, NC_LINK, true);
  650.             link = link.QueryInterface(Components.interfaces.nsIRDFLiteral);
  651.  
  652.             urnID++;
  653.             resultsDS.Assert(RDF_ROOT,
  654.                 RDF.GetResource("http://home.netscape.com/NC-rdf#child"),
  655.                 RDF.GetResource("urn:" + urnID),
  656.                 true);
  657.             resultsDS.Assert(RDF.GetResource("urn:" + urnID),
  658.                  RDF.GetResource("http://home.netscape.com/NC-rdf#name"),
  659.                  name,
  660.                  true);
  661.              resultsDS.Assert(RDF.GetResource("urn:" + urnID),
  662.                 RDF.GetResource("http://home.netscape.com/NC-rdf#link"),
  663.                 link,
  664.                 true);
  665.             emptySearch = false;
  666.         }
  667.         // process any nested rdf:seq elements.
  668.         doFindOnDatasource(resultsDS, sourceDS, target, level+1);
  669.     }
  670. }
  671.  
  672. function assertSearchEmpty(resultsDS) {
  673.     var resSearchEmpty = RDF.GetResource("urn:emptySearch");
  674.     resultsDS.Assert(RDF_ROOT,
  675.         NC_CHILD,
  676.         resSearchEmpty,
  677.         true);
  678.     resultsDS.Assert(resSearchEmpty,
  679.         NC_NAME,
  680.         RDF.GetLiteral(emptySearchText),
  681.         true);
  682.     resultsDS.Assert(resSearchEmpty,
  683.         NC_LINK,
  684.         RDF.GetLiteral(emptySearchLink),
  685.         true);
  686. }
  687.  
  688. function isMatch(text) {
  689.     for (var i=0; i < RE.length; ++i ) {
  690.         if (!RE[i].test(text)) {
  691.             return false;
  692.         }
  693.     }
  694.     return true;
  695. }
  696.  
  697. function loadCompositeDS(datasources) {
  698.     var compositeDS =  Components.classes["@mozilla.org/rdf/datasource;1?name=composite-datasource"]
  699.         .createInstance(Components.interfaces.nsIRDFCompositeDataSource);
  700.  
  701.     var ds = datasources.split(/\s+/);
  702.     for (var i=0; i < ds.length; ++i) {
  703.         if (ds[i] == "rdf:null" || ds[i] == "") {
  704.             continue;
  705.         }
  706.         try {
  707.             // we need blocking here to ensure the database is loaded.
  708.             var sourceDS = RDF.GetDataSourceBlocking(ds[i]);
  709.             compositeDS.AddDataSource(sourceDS);
  710.         } catch (e) {
  711.             log("Datasource: " + ds[i] + " was not found.");
  712.         }
  713.     }
  714.     return compositeDS;
  715. }
  716.  
  717. function getAttribute(datasource, resource, attributeResourceName,
  718.         defaultValue) {
  719.     var literal = datasource.GetTarget(resource, attributeResourceName, true);
  720.     if (!literal) {
  721.         return defaultValue;
  722.     }
  723.     return getLiteralValue(literal, defaultValue);
  724. }
  725.  
  726. function getLiteralValue(literal, defaultValue) {
  727.     if (literal) {
  728.         literal = literal.QueryInterface(Components.interfaces.nsIRDFLiteral);
  729.         if (literal) {
  730.             return literal.Value;
  731.         }
  732.     }
  733.     if (defaultValue) {
  734.         return defaultValue;
  735.     }
  736.     return null;
  737. }
  738.  
  739. function log(aText) {
  740.     CONSOLE_SERVICE.logStringMessage(aText);
  741. }
  742.  
  743. function expandAllIndexEntries() {
  744.     var treeview = helpIndexPanel.view;
  745.     var i = treeview.rowCount;
  746.     while (i--) {
  747.         if (!treeview.getLevel(i) && !treeview.isContainerOpen(i)) {
  748.             treeview.toggleOpenState(i);
  749.         }
  750.     }
  751. }
  752.  
  753. function toggleSidebar()
  754. {
  755.     var sidebar = document.getElementById("helpsidebar-box");
  756.     var separator = document.getElementById("helpsidebar-splitter");
  757.     var sidebarButton = document.getElementById("help-sidebar-button");
  758.  
  759.     //Use the string bundle to retrieve the text "Hide Sidebar"
  760.     //and "Show Sidebar" from the locale directory.
  761.     var strBundle = document.getElementById("bundle_help");
  762.     if (sidebar.hidden) {
  763.       sidebar.removeAttribute("hidden");
  764.       sidebarButton.label = strBundle.getString("hideSidebarLabel");
  765.  
  766.       separator.removeAttribute("hidden");
  767.     } else {
  768.       sidebar.setAttribute("hidden","true");
  769.       sidebarButton.label = strBundle.getString("showSidebarLabel");
  770.  
  771.       separator.setAttribute("hidden","true");
  772.     }
  773. }
  774.  
  775. // Shows the panel relative to the currently selected panel.
  776. // Takes a boolean parameter - if true it will show the next panel, 
  777. // otherwise it will show the previous panel.
  778. function showRelativePanel(goForward) {
  779.   var selectedIndex = -1;
  780.   var sidebarBox = document.getElementById("helpsidebar-box");
  781.   var sidebarButtons = new Array();
  782.   for (var i = 0; i < sidebarBox.childNodes.length; i++) {
  783.     var btn = sidebarBox.childNodes[i];
  784.     if (btn.nodeName == "toolbarbutton") {
  785.       if (btn.getAttribute("selected") == "true")
  786.         selectedIndex = sidebarButtons.length;
  787.       sidebarButtons.push(btn);
  788.     }
  789.   }
  790.   if (selectedIndex == -1)
  791.     return;
  792.   selectedIndex += goForward ? 1 : -1;
  793.   if (selectedIndex >= sidebarButtons.length)
  794.     selectedIndex = 0;
  795.   else if (selectedIndex < 0)
  796.     selectedIndex = sidebarButtons.length - 1;
  797.   sidebarButtons[selectedIndex].doCommand();
  798. }
  799.  
  800.